package cn.zhz.cloud.gateway.util;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import cn.zhz.cloud.common.model.result.R;
import cn.zhz.cloud.common.model.result.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;

/**
 * @author ZHZ
 * @date 2022-08-19
 * @apiNote
 */
@Slf4j
public class AuthVerify {


    /**
     * 权限校验
     *
     * @param exchange
     * @param chain
     * @param consumer
     * @return
     */
    public static Mono<Void> verify(ServerWebExchange exchange, GatewayFilterChain chain, Consumer<ServerWebExchange> consumer) {
        try {
            consumer.accept(exchange);
            return chain.filter(exchange);
        } catch (StopMatchException stopMatchException) {
            log.debug("停止匹配");
            return chain.filter(exchange);
        } catch (NotLoginException notLoginException) {
            log.error(notLoginException.getMessage());
            return getVoidMono(exchange, R.failed(ResultCode.UNAUTHORIZED, notLoginException.getMessage(), null), HttpStatus.UNAUTHORIZED);
        } catch (NotPermissionException notPermissionException) {
            log.error(notPermissionException.getMessage());
            return getVoidMono(exchange, R.failed(ResultCode.FORBIDDEN, notPermissionException.getMessage(), null), HttpStatus.FORBIDDEN);
        }
    }

    /**
     * 网关抛异常
     *
     * @param body
     */
    private static Mono<Void> getVoidMono(ServerWebExchange serverWebExchange, R body, HttpStatus status) {
        serverWebExchange.getResponse().setStatusCode(status);
        byte[] bytes = JSONUtil.toJsonStr(body, new JSONConfig().setIgnoreNullValue(false)).getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = serverWebExchange.getResponse().bufferFactory().wrap(bytes);
        return serverWebExchange.getResponse().writeWith(Flux.just(buffer));
    }
}
